package features;

import com.vividsolutions.jts.geom.Dimension;
import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JButton;
import javax.swing.JToolBar;

import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.DefaultMapContext;
import org.geotools.map.Layer;
import org.geotools.map.MapContext;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.Fill;
import org.geotools.styling.Graphic;
import org.geotools.styling.Mark;
import org.geotools.styling.Rule;
import org.geotools.styling.Stroke;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.Symbolizer;
import org.geotools.swing.JMapFrame;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.geotools.swing.event.MapMouseEvent;
import org.geotools.swing.tool.CursorTool;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.identity.FeatureId;

import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon;
import org.geotools.map.FeatureLayer;

import dbf.DBFdata;
import dbf.ModeloTabela;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.table.TableModel;
import org.geotools.data.FeatureSource;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.shapefile.dbf.DbaseFileReader;
import org.geotools.filter.text.cql2.CQL;
import org.geotools.map.DefaultMapContext;
import org.geotools.map.MapContext;
import org.geotools.swing.JMapFrame;
import org.geotools.swing.MapLayerTable;
import org.geotools.swing.StatusBar;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.geotools.swing.event.MapMouseEvent;
import org.geotools.swing.tool.CursorTool;
import sun.awt.HorizBagLayout;


public class Selecao extends JFrame{
    static JTable tabelaDBF = new JTable();
    static int regiaoSelecTabela;
    /*
     * Factories that we will use to create style and filter objects
     */
    private StyleFactory sf = CommonFactoryFinder.getStyleFactory(null);
    private FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);

    /*
     * Convenient constants for the type of feature geometry in the shapefile
     */
    private enum GeomType { POINT, LINE, POLYGON };

    /*
     * Some default style variables
     */
     private final Color cores[] = {Color.black, Color.blue, Color.cyan, Color.darkGray,Color.gray, Color.green, Color.lightGray,Color.magenta,Color.orange, Color.pink, Color.red, Color.white, Color.yellow};

    Random randomColor = new Random();
    private static final Color LINE_COLOUR = Color.BLUE;
    private static final Color FILL_COLOUR= Color.CYAN;
    public static Color SELECTED_COLOUR = Color.YELLOW;
    private static final float OPACITY = 1.0f;
    private static final float LINE_WIDTH = 1.0f;
    private static final float POINT_SIZE = 10.0f;

    private JMapFrame mapFrame;
    private SimpleFeatureSource featureSource;

    private String geometryAttributeName;
    private GeomType geometryType;

      public void displayShapefile(File file) throws Exception {
        FileDataStore store = FileDataStoreFinder.getDataStore(file);
        featureSource = store.getFeatureSource();
        setGeometry();

        /*
         * Create the JMapFrame and set it to display the shapefile's features
         * with a default line and colour style
         */
        MapContext map = new DefaultMapContext();
        map.setTitle("Feature selection tool example");
        Style style = createDefaultStyle();
        map.addLayer(featureSource, style);
        mapFrame = new JMapFrame(map);
        mapFrame.enableToolBar(true);
        mapFrame.enableStatusBar(true);


      //  StatusBar statusBar = new StatusBar(mapFrame.getMapPane());
        //statusBar.gC

        final JPanel painelDBF = new JPanel();

       
         String dbf = file.toString();
        dbf= dbf.substring(0, dbf.length() - 3);
        dbf = dbf + "dbf";
        File f = new File (dbf);

        int numeroColunasDBF = DBFdata.numeroColunas(f);
        int numeroLinhasDBF = DBFdata.numeroLinhas(f);
        System.out.println("linhas: " + numeroLinhasDBF + " colunas: "+ numeroColunasDBF);//imprime os indices das colunas

         tabelaDBF.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);// ativa barra de rolagem horizontal
        tabelaDBF.setModel(new ModeloTabela(DBFdata.cabecalhoTabela(f), numeroLinhasDBF, numeroColunasDBF));

        //DBFdata.matrizDados(f);
          for (int i = 0; i < numeroLinhasDBF; i++) {

                        for (int j = 0; j <numeroColunasDBF; j++) {

                        //System.out.println("TESTE DO OBJECT na linha: " + i + " com valor: " + aobj[j]);
                        tabelaDBF.setValueAt(DBFdata.matrizDados(f,i,j), i, j);
                        //System.out.println(DBFdata.matrizDados(f,i,j));
                        }
                    }
                    
                  //  tabelaDBF.getSelectionModel().setSelectionInterval (1, 1);
                    //System.out.println("teste "+tabelaDBF.getValueAt(1, 1));
//tabelaDBF.setPreferredSize(new Dimension(500, 70));
                   //jlist1.setVisibleRowCount(4);
        JScrollPane scrollPane = new JScrollPane(tabelaDBF);


                    scrollPane.setLocation(0, 0);
                    //scrollPane.setSize(10, 300);
                    //scrollPane.setSize(painelDBF.getWidth()-2, 97);
                    //Dimension dimensao = new Dimension(400, 98);       //Usado para definir o tamanho visível (sem uso do scroll) da tabela
                    //scrollPane.setPreferredSize(dimensao);
                   // painelDBF.add(scrollPane);
                    //painelDBF.setVisible(true);
        /*
         * Before making the map frame visible we add a new button to its
         * toolbar for our custom feature selection tool
         */
        JToolBar toolBar = mapFrame.getToolBar();
        JButton btn = new JButton("Select");
        toolBar.addSeparator();
        toolBar.add(btn);
        toolBar.addSeparator();

        

        //toolBar.setOrientation(JToolBar.RIGHT);
         //toolBar.setLocation(100, 100);

       toolBar.add( scrollPane );


       
        /*
         * When the user clicks the button we want to enable
         * our custom feature selection tool. Since the only
         * mouse action we are intersted in is 'clicked', and
         * we are not creating control icons or cursors here,
         * we can just create our tool as an anonymous sub-class
         * of CursorTool.
         */
        btn.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                mapFrame.getMapPane().setCursorTool(
                        new CursorTool() {

                            @Override
                            public void onMouseClicked(MapMouseEvent ev) {
                                selectFeatures(ev);
                                tabelaDBF.setRowSelectionInterval(regiaoSelecTabela-1, regiaoSelecTabela-1);
//                                tabelaDBF.changeSelection(regiaoSelecTabela - 1, 0, false, false);
//                                tabelaDBF.scrollRectToVisible(tabelaDBF.getCellRect(regiaoSelecTabela, 0, true));
                            }
                        });
            }
        });
        tabelaDBF.addMouseListener(new MouseAdapter() {
    public void mouseClicked(MouseEvent e)
    {
        if (e.getClickCount() == 2)
        {
                    try {
                        Point p = e.getPoint();
                        int row = tabelaDBF.rowAtPoint(p)+1;
                        //int col = tabelaDBF.columnAtPoint(p);
                        String linha =  "" + row;
                        selectFeatures2(linha);
                        //SELECTED_COLOUR = Color.BLACK;
                        mapFrame.getMapPane().repaint();
                        //System.out.printf("row: %d    col: %d\n", row, col);
                        //                    try {
                        //                        selectFeatures2(row);
                        //                        //            tabelaDBF.scrollRectToVisible(tabelaDBF.getCellRect(regiaoSelecTabela, 0, true));
                        //                        //            tabelaDBF.scrollRectToVisible(tabelaDBF.getCellRect(regiaoSelecTabela, 0, true));
                        //                    } catch (IOException ex) {
                        //                    }
                        //                    }
                    } catch (IOException ex) {
                        Logger.getLogger(Selecao.class.getName()).log(Level.SEVERE, null, ex);
                    }





        }
    }
});
      






        /**
         * Finally, we display the map frame. When it is closed
         * this application will exit.
         */
        mapFrame.setSize(600, 600);
        mapFrame.setVisible(true);
       
    }
    /**
     * This method is called by our feature selection tool when
     * the user has clicked on the map.
     *
     * @param pos map (world) coordinates of the mouse cursor
     */
      void selectFeatures2(String row) throws IOException {

            SimpleFeatureCollection selectedFeatures =
                    featureSource.getFeatures();

            SimpleFeatureIterator iter = selectedFeatures.features();
            Set<FeatureId> IDs = new HashSet<FeatureId>();

                while (iter.hasNext()) {
                   SimpleFeature feature = iter.next();
                   //"BR_Regioes.4";
                 // int cont = 0;
                  //System.out.println(feature.getIdentifier() + " OK");

//                   for(int i = 0; i < (feature.getID().length() - row.length() + 1); i++){
//                        String res = feature.getID().substring(i, (i + row.length()));
//                        if(res.equals(row)){
//                           IDs.add(feature.getIdentifier());
//                           System.out.println(feature.getIdentifier() + " OK");
//                           break;
//                        }
//                  }
                String aux ="";
                   for(int i = 0; i < feature.getID().toString().length(); i++){
        Character caractere = feature.getID().charAt(i);
        if(caractere.equals('0') ||caractere.equals('1') ||caractere.equals('2') ||caractere.equals('3')||caractere.equals('4')||caractere.equals('5')||caractere.equals('6')||caractere.equals('7')||caractere.equals('8')||caractere.equals('9'))
        {    //!Character.isDigit(caractere) && !caractere.equals("_")){
            aux = aux + caractere;

        }
    }
                if(aux.equals(row)){
                           IDs.add(feature.getIdentifier());
                           System.out.println(feature.getIdentifier() + " OK");

                        }


          }
             displaySelectedFeatures(IDs);

      }



    void selectFeatures(MapMouseEvent ev) {

      //  System.out.println("Mouse click at: " + ev.getMapPosition());

        /*
         * Construct a 5x5 pixel rectangle centred on the mouse click position
         */
        Point screenPos = ev.getPoint();
        Rectangle screenRect = new Rectangle(screenPos.x-2, screenPos.y-2, 5, 5);

        /*
         * Transform the screen rectangle into bounding box in the coordinate
         * reference system of our map context. Note: we are using a naive method
         * here but GeoTools also offers other, more accurate methods.
         */
        AffineTransform screenToWorld = mapFrame.getMapPane().getScreenToWorldTransform();
        Rectangle2D worldRect = screenToWorld.createTransformedShape(screenRect).getBounds2D();
        ReferencedEnvelope bbox = new ReferencedEnvelope(
                worldRect,
                mapFrame.getMapContext().getCoordinateReferenceSystem());

        /*
         * Create a Filter to select features that intersect with
         * the bounding box
         */
        Filter filter = ff.intersects(ff.property(geometryAttributeName), ff.literal(bbox));

        /*
         * Use the filter to identify the selected features
         */
        try {
            SimpleFeatureCollection selectedFeatures =
                    featureSource.getFeatures(filter);

            SimpleFeatureIterator iter = selectedFeatures.features();
            Set<FeatureId> IDs = new HashSet<FeatureId>();
            try {
                while (iter.hasNext()) {
                    SimpleFeature feature = iter.next();
                    IDs.add(feature.getIdentifier());

                  ///////////////////////////////Link entre Mapa-tabela
                    int k, tamanhoVariavel = feature.getIdentifier().toString().length();
                    for (k = 0; k < tamanhoVariavel; k++) {
                        if (isNumeric(feature.getIdentifier().toString().charAt(tamanhoVariavel-1))) {
                            tamanhoVariavel--;
                        }
                        else
                        {
                            break;
                        }

                    }
                    regiaoSelecTabela = Integer.parseInt(feature.getIdentifier().toString().substring(feature.getIdentifier().toString().length() - k, feature.getIdentifier().toString().length()));
                    System.out.println("aqui2 ");

                    System.out.println("   " + feature.getIdentifier());
                    /////////////////
                }

            } finally {
                iter.close();
            }

            if (IDs.isEmpty()) {
                System.out.println("   no feature selected");
            }

            displaySelectedFeatures(IDs);

        } catch (Exception ex) {
            ex.printStackTrace();
            return;
        }
    }
     /**
     * Sets the display to paint selected features yellow and
     * unselected features in the default style.
     *
     * @param IDs identifiers of currently selected features
     */
    public void displaySelectedFeatures(Set<FeatureId> IDs) {
        Style style;

        if (IDs.isEmpty()) {
            style = createDefaultStyle();

        } else {
            style = createSelectedStyle(IDs);
        }

        Layer layer = mapFrame.getMapContext().layers().get(0);
        ((FeatureLayer) layer).setStyle(style);
        mapFrame.getMapPane().repaint();
    }
    /**
     * Create a default Style for feature display
     */
    private Style createDefaultStyle() {
        Rule rule = createRule(LINE_COLOUR, FILL_COLOUR);

        FeatureTypeStyle fts = sf.createFeatureTypeStyle();
        fts.rules().add(rule);

        Style style = sf.createStyle();
        style.featureTypeStyles().add(fts);
        return style;
    }
     /**
     * Create a Style where features with given IDs are painted
     * yellow, while others are painted with the default colors.
     */
    private Style createSelectedStyle(Set<FeatureId> IDs) {
        Rule selectedRule = createRule(SELECTED_COLOUR, SELECTED_COLOUR);
        selectedRule.setFilter(ff.id(IDs));

        Rule otherRule = createRule(LINE_COLOUR, FILL_COLOUR);
        otherRule.setElseFilter(true);

        FeatureTypeStyle fts = sf.createFeatureTypeStyle();
        fts.rules().add(selectedRule);
        fts.rules().add(otherRule);

        Style style = sf.createStyle();
        style.featureTypeStyles().add(fts);
        return style;
    }
     /**
     * Helper for createXXXStyle methods. Creates a new Rule containing
     * a Symbolizer tailored to the geometry type of the features that
     * we are displaying.
     */
    private Rule createRule(Color outlineColor, Color fillColor) {
        Symbolizer symbolizer = null;
        Fill fill = null;
        Stroke stroke = sf.createStroke(ff.literal(outlineColor), ff.literal(LINE_WIDTH));

        switch (geometryType) {
            case POLYGON:
                fill = sf.createFill(ff.literal(fillColor), ff.literal(OPACITY));
                symbolizer = sf.createPolygonSymbolizer(stroke, fill, geometryAttributeName);
                break;

            case LINE:
                symbolizer = sf.createLineSymbolizer(stroke, geometryAttributeName);
                break;

            case POINT:
                fill = sf.createFill(ff.literal(fillColor), ff.literal(OPACITY));

                Mark mark = sf.getCircleMark();
                mark.setFill(fill);
                mark.setStroke(stroke);

                Graphic graphic = sf.createDefaultGraphic();
                graphic.graphicalSymbols().clear();
                graphic.graphicalSymbols().add(mark);
                graphic.setSize(ff.literal(POINT_SIZE));

                symbolizer = sf.createPointSymbolizer(graphic, geometryAttributeName);
        }

        Rule rule = sf.createRule();
        rule.symbolizers().add(symbolizer);
        return rule;
    }
     /**
     * Retrieve information about the feature geometry
     */
    private void setGeometry() {
        GeometryDescriptor geomDesc = featureSource.getSchema().getGeometryDescriptor();
        geometryAttributeName = geomDesc.getLocalName();

        Class<?> clazz = geomDesc.getType().getBinding();

        if (Polygon.class.isAssignableFrom(clazz) ||
                MultiPolygon.class.isAssignableFrom(clazz)) {
            geometryType = GeomType.POLYGON;

        } else if (LineString.class.isAssignableFrom(clazz) ||
                MultiLineString.class.isAssignableFrom(clazz)) {

            geometryType = GeomType.LINE;

        } else {
            geometryType = GeomType.POINT;
        }

    }
    public boolean isNumeric(char s) {
        String teste = "" + s;
        try {
            Long.parseLong(teste);
            return true;
        } catch (NumberFormatException ex) {
            return false;
        }
    }
}